package juc;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 手动实现CAS
 *
 * @author hck
 */
public class TestCAS {
    public static void main(String[] args) throws InterruptedException {
        AtomicIncrease atomicIncre = new AtomicIncrease();
        final int threadCount = 1000;
        final int increCount =  10000;
        CountDownLatch countDownLatch = new CountDownLatch(threadCount);
        //  生产环境禁止使用 Executors 创建,因为会隐藏很多线程池细节.
        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
        for (int i = 0; i < threadCount; i++) {
            executorService.submit(() -> {
                for (int j = 0; j < increCount; j++) {
                    atomicIncre.incre();
                }
                countDownLatch.countDown();
            });
        }
        //  等待任务完成
        countDownLatch.await();
        System.out.println("累加结果:" + atomicIncre.get());
        System.out.println("自旋次数:" + atomicIncre.getCount());
        //  关闭线程池
        executorService.shutdown();
    }
}

class AtomicIncrease {
    private volatile int value = 0;
    private AtomicInteger count = new AtomicInteger();

    public void incre() {
        int old;
        do {
            old = value;
            count();
        } while (!setValue(old, old + 1));
    }

    /**
     * 交換操作必須是原子的所以需要加锁
     *
     * @param old   需要比较的旧数据
     * @param fresh 新数据
     * @return 是否设置成功
     */
    private synchronized boolean setValue(int old, int fresh) {
        if (old == value) {
            value = fresh;
            return true;
        }
        return false;
    }

    public int get() {
        return value;
    }

    /**
     * 获取自旋次数
     *
     * @return 自旋次数
     */
    public int getCount() {
        return this.count.get();
    }

    /**
     * 计算自旋次数,最少自旋 100 * 1000 次
     */
    private void count() {
        count.getAndIncrement();
    }
}
